﻿/// <reference path="jquery/jquery.js" />
/// <reference path="jquery/jquery-ui.custom.js" />
/// <reference path="jquery/jquery.ui.core.js" />
/// <reference path="jquery/jquery.ui.widget.js" />
/// <reference path="jquery/jquery.ui.position.js" />
/// <reference path="jquery/jquery.ui.autocomplete.js" />

/*
*  Autor........................: Edney Batista da Silva
*  Data.........................: 30-04-2013
*  Descrição....................: Script para gerar autocomplete
*/


var eCompletes = {};
/*
*  Objeto que contém as configurações do auto complete
*  Id.................: o eId único do objeto o qual será a sua chave de recuperação do container de objetos de autocomplete
*  Target.............: o input que recebe as entradas do autocomplete
*  Config.............: Contém as configurações para a requisição e a resposta 
*      RequestType....: Tipo da requisição (get | post)
*      ContentType....: Tipo do dado sendo enviado (xml | json | html | text | jsonp)
*      Url............: Url a ser requisitada para fazer a busca
*      DataType.......: Tipo do dado de resposta (json | jsonp | html | text | xml)
*      IsAsync........: define se é uma requisição assincrona ou não  (true | false)
*      error..........: função que ocorrerá em caso de erro(function)
*      Templeted......: identifica se será renderizado o response de maneira customizada(true | false)
*                       se true o item terá que implementar o evento onRender
*/
EComplete = function () {
    return {
        Id: "",
        Target: null,
        Config: {
            RequestType: "Post",
            ContentType: "application/json; charset=utf-8",
            Url: "",
            DataType: "json",
            IsAsync: true,
            onError: null,
            Templeted: false,
            Length: 1,
            OnSelected: null
        }
    }
}

/*
*  Função para disparar eventos customizados
*/
function __trigger(element, name, args, returnValue) {
    // cria os parametros
    var __param = ""
    for (var i in args) {
        __param += (__param.length > 0 ? ", " : "") + "e." + i;
    }
    // cria a função anônima para disparo
    var __func = Function("e",
                    "with(document){" +
                        "with(this){" +
                            (returnValue ? "return " : "") + element.getAttribute((name.indexOf("on") > -1 ? name : "on" + name)) +
                            "(" + __param + ")" +
                        "}" +
                    "}"
                 );
    // invoca o evento
    return __func.call(element, args);
}
$(function () {
    /*
    *  Obtém todos os inputs que seram autocompletes
    */
    $("input[auto-complete='true']").each(function (e) {
        // obtém o eId do elemento
        var eId = $(this).attr("eId");
        if (!eId)
            throw "O objeto precisa do atributo eId, e o mesmo não está definido";
        // cria instância e preenche as propriedades
        var $e = new EComplete();
        $e.Id = eId;
        $e.Target = this;
        for (var i in $e.Config) {
            var type = typeof $e.Config[i];
            $e.Config[i] = $(this).attr(i) ? $(this).attr(i) : $e.Config[i];
            if (type === "boolean" && typeof $e.Config[i] != type) {
                $e.Config[i] = $e.Config[i].toLowerCase().indexOf("true") > -1;
            }
        }
        // cria cache em memória do objeto
        eCompletes[eId] = $e;
        var current = this;
        // cria objeto autocomplete
        var completeObject = $(this).autocomplete({
            source: function (request, response) {
                // obtém o input corrente
                var element = $(this.element).get(0);
                // obtém a instância de EComplete do input
                var __e = $e || eCompletes[$(this.element).attr("eId")];
                // fazer implementação de tipo de parametros
                var param = ""
                // faz a chamada ajax
                $.ajax({
                    type: __e.Config.RequestType,
                    contentType: __e.Config.ContentType,
                    url: __e.Config.Url,
                    data: "{'termo':'" + request.term + "'}",
                    dataType: __e.Config.DataType,
                    async: __e.Config.IsAsync,
                    success: function (data) {
                        // verifica o conteúdo da resposta e invoca o método para criar o autocomplete
                        response(data.d ? data.d : data.responseText ? data.responseText : data);
                    },
                    error: function (result) {
                        // dispara evento em caso de falha
                        //alert("Due to unexpected errors we were unable to load data");
                        if (__e.Config.onError != null) {
                            __trigger(element, "onError", { result: result });
                        }
                    }
                });
            },
            select: function (event, ui) {
                // obtém a instância de EComplete do input
                var __e = $e || eCompletes[$(this.element).attr("eId")];
                // obtém o input corrente
                var element = __e.Target
                if (__e.Config.OnSelected != null) {
                    return __trigger(element, "onSelected", { event: event, ui: ui, context: this }, true);
                }

            },
            minLength: ($e.Config && $e.Config.Length ? $e.Config.Length : 0)
        });


        // cria disparador de renderização customizada
        if ($e.Config.Templeted) {
            completeObject.data("autocomplete")._renderItem = function (ul, item) {
                // obtém o elemento
                var element = $(this.element).get(0);
                if (element) {
                    // dispara o evento onRender
                    return __trigger(element, "Render", { ul: ul, item: item }, true);
                }
            }
        }
    });
});